package com.bitoon.basketdudes.web.mensajeria;

import com.bitoon.basketdudes.jpa.PersistenceManager;
import com.bitoon.basketdudes.web.datos.InfoCabeceraXHR;
import com.bitoon.basketdudes.jpa.Usuario;
import java.net.URLDecoder;
import java.util.*;
import javax.persistence.*;

import org.apache.log4j.Logger;

public class MensajesV2 {

    protected EntityManagerFactory emfBasket = null;

    private List<Hilo> listaHilos;      //es una lista de hilos(los hilos son listas de mensajes)
    private Hilo datos;                 //es una lista de mensajes de una conversacion

    private String archivar;            // Para recibir el id del hilo a archivar
    private String asunto;
    private String destinatario;      // Para recibir los ids del envio de mensaje a uno/varios users
    private String[] idsUsuario;
    private String nicks;
    private String cuerpo;
    private boolean error;
    private String marcaAnoLeido;       //Para recibir el id de la conversacion a marcar como no leida
    private String cargarHilo;          //Para recibir el id del hilo a cargar sus mensajes
    private int numHiloRespuesta;       //cuando se responda contendra el num de hilo a insertar el msg respuesta
    private MensajeUsuarioV2 respuesta; //Para almacenar el mensaje de vuelta cuandos es respuesta
    private int idHilo;
    private String mensajes;

    private InfoCabeceraXHR cabecera;

    private Logger log = Logger.getLogger(MensajesV2.class);

    private int numMensajesBandejaEntrada = 0;

    private Usuario usuarioLogado = null; // IMPLEMENTAR

    public MensajesV2() {
        String catalogos[] = {"jpa_catalogo", "jpa_basket"};
        try {
            // JPA Units
//            emfCatalogo = PersistenceManager.getInstance().getEntityManagerFactory(catalogos[0]);
//            emfBasket = PersistenceManager.getInstance().getEntityManagerFactory(catalogos[1]);

            emfBasket = PersistenceManager.getInstance().getEntityManagerFactory("jpa_basket");
        } catch (Exception e) {
            log.error("[ERROR][constructor]: No se pudo conectar a la base de datos: ", e);
        }
    }

    public void logarUsuario(int idUsuario) {
        log.debug("logando usuario " + idUsuario);
        EntityManager em = null;
        try {
            em = emfBasket.createEntityManager(); // check 08.08.2012
            Query q = em.createNamedQuery("Usuario.findById");
            q.setParameter("id", idUsuario);
            Usuario u = (Usuario)q.getSingleResult();
            log.debug("u: " + u);
            setUsuarioLogado(u);
        } catch (Exception e) {
            log.error("[logarUsuario]: " , e);
            if (em     != null && em.getTransaction().isActive() )
                em.getTransaction().rollback();
        } finally {
            try { if (em != null) em.close(); } catch (Exception e) { }; // revisado 09/08/2012
        }
    }

    public void recibidos() {
        
        if (getUsuarioLogado()!=null) {
            log.debug("en recibidos ...");
            GestorHilos gh = new GestorHilos(getUsuarioLogado().getId());
            setListaHilos(gh.LeerHilos());

            if (getListaHilos()!=null) {
                int no_leidos=0;
                for(Hilo h : getListaHilos()){
                    //si un hilo esta sin leer, acumulamos los no leidos
                    if(h.getEstado()==0){
                        ++no_leidos;
                    }
                }
                setNumMensajesBandejaEntrada(no_leidos);
            } else {
                setNumMensajesBandejaEntrada(0);
            }
        }
    }

    public void escribirMensajeNormal(){
        MensajeUsuarioV2 mu = null;
        EntityManager    em = null;

        try {

            log.debug("Id destinatario/s: " + destinatario +" mensaje: " + cuerpo);

            cabecera = new InfoCabeceraXHR();
            cabecera.setCorrecto(1);

            if (destinatario!=null && destinatario.length()>0 && cuerpo!=null && cuerpo.compareTo("")!=0) {

                String tdest = destinatario.replaceAll("%252c", ",");
                destinatario = destinatario.replaceAll("%2c", ",");
                log.debug("tdest: " + tdest);
                idsUsuario = tdest.split(",");

                log.debug("Nuevooooooo");

                for (String s: idsUsuario) {
                    log.debug("1 >>>>> " + (s.trim()).toLowerCase());
                    log.debug("2 >>>> " + (s.trim()));
                    log.debug("3 >>>> " + s);
                }

                //tenemos que añadir al usuario al idDestinatarios al estilo facebook, para que siempre
                //tenga ese mensaje como hilo suyo, si es un mensaje nuevo
                if (numHiloRespuesta==0) {
                    completaDestinatariosConEmisor();
                }

                Usuario ul = getUsuarioLogado();

                mu = new MensajeUsuarioV2();
                mu.setSender(ul.getId());
                mu.setFrom(ul.getNickMostrar());
                mu.setFromUrl(ul.getNick());
                //mu.setAsunto(getAsunto());
                //mu.setTexto(escapeHtml(cuerpo));
                mu.setTexto(URLDecoder.decode(cuerpo, "UTF8"));
                mu.setTipoUsuarioEmisor(MensajeUsuarioV2.TIPO_USUARIO_NORMAL);
                mu.setEstado(0);

                Hilo h = new Hilo();

                h.setCreador(getUsuarioLogado().getId());
                //añadimos a los participantes
                String participantes = "";
                em = emfBasket.createEntityManager(); // check 08.08.2012
                Query q = null;
                Usuario u = null;

                log.debug("numHiloRespuesta: " + numHiloRespuesta);
                
                for (String s: idsUsuario) {
                    log.debug("1 >>>>> " + (s.trim()).toLowerCase());
                    log.debug("2 >>>> " + (s.trim()));
                    log.debug("3 >>>> " + s);
                }

                boolean ponercoma = false;
                for(String s: idsUsuario){

                    if (ponercoma) {
                        participantes += ",";
                    } else {
                        ponercoma = true;
                    }

                    if(numHiloRespuesta==0){ //si es un nuevo mensaje
                        q = em.createNamedQuery("Usuario.findByNick");
                        log.debug("arrebuscando " + (s.trim()).toLowerCase());
                        q.setParameter("nick", (s.trim()).toLowerCase());
                    } else {
                        //si es una respuesta
                        q = em.createNamedQuery("Usuario.findById");
                        q.setParameter("id", Integer.parseInt(s.trim()));
                    }

                    u = (Usuario)q.getSingleResult();
                    participantes = participantes + Integer.toString(u.getId()).trim();
                }

                //El/los receptor(es) lo(s) sacamos de id(s) pasado(s)
                mu.setTo(participantes);
                h.getListaMensajes().add(mu);
                h.setParticipantes(participantes);

                GestorHilos gh = new GestorHilos(getUsuarioLogado().getId());
                if (gh.Grabar(h,numHiloRespuesta)==true) {
                    cabecera.setCorrecto(0);
                    log.debug("Error: al escribir el hilo o mensaje");
                }
            }else{
                cabecera.setCorrecto(0);
                log.debug("Error: no hay destinatario o mensaje vacio");
            }

            setCabecera(cabecera);
        } catch (Exception e) {
            log.error("[logarUsuario]: " , e);
            if (em     != null && em.getTransaction().isActive() )
                em.getTransaction().rollback();
        } finally {
            try { if (em != null) em.close(); } catch (Exception e) { }; // revisado 09/08/2012
        }
        
    }

    public void respuestaMensaje(){


        if (getUsuarioLogado().getId() > 0) {
            log.debug("[respuestaMensaje] entro,partes: " + cargarHilo);

            //sacamos el hilo
            String[] partes = cargarHilo.split("-"); //idHilo_idMsg-participantes(separados por comas)
            setNumHiloRespuesta(Integer.parseInt(partes[0])); //id del hilo
            //sacamos los destinatarios
            //idDestinatario = partes[1];

            //escribimos la respuesta en el hilo
            escribirMensajeNormal();
        }
    }

    /*
    private void escribirMensajeNormal(){
        MensajeUsuarioV2 mu =null;

        log.debug("Id destinatario/s: " + destinatario +" cuerpo: " + cuerpo);

        setCabecera(new InfoCabeceraXHR());
        getCabecera().setCorrecto(1);

        if (getDestinatario()!=null && getDestinatario().length()>0 && getCuerpo()!=null && getCuerpo().compareTo("")!=0) {

            setIdsUsuario(getDestinatario().split(","));

            //tenemos que añadir al usuario al idDestinatarios al estilo facebook, para que siempre
            //tenga ese mensaje como hilo suyo, si es un mensaje nuevo
            if(getNumHiloRespuesta()==0){
                completaDestinatariosConEmisor();
            }

            Usuario ul = getUsuarioLogado();

            mu = new MensajeUsuarioV2();
            mu.setSender(ul.getId());
            mu.setFrom(ul.getNickMostrar());
            mu.setFromUrl(ul.getNick());
            //mu.setAsunto(getAsunto());
            mu.setTexto(getCuerpo());
            mu.setTipoUsuarioEmisor(MensajeUsuarioV2.TIPO_USUARIO_NORMAL);
            mu.setEstado(0);

            Hilo h = new Hilo();

            h.setCreador(getUsuarioLogado().getId());
            //añadimos a los participantes
            String participantes = "";
            EntityManager em = emfBasket.createEntityManager(); // check 08.08.2012
            Query q = null;
            Usuario u = null;

            for(int i=0;i<getIdsUsuario().length;++i){

                if(getNumHiloRespuesta()==0){ //si es un nuevo mensaje
                    q = em.createNamedQuery("Usuario.findByNick");
                    q.setParameter("nick", getIdsUsuario()[i].trim().toLowerCase());
                }else{
                    //si es una respuesta
                    q = em.createNamedQuery("Usuario.findById");
                    q.setParameter("id", Integer.parseInt(getIdsUsuario()[i].trim()));
                }

                try {
                    u = (Usuario)q.getSingleResult();
                    participantes = participantes + Integer.toString(u.getId()).trim();
                } catch (NoResultException nre) {
                }

                if((i+1)<getIdsUsuario().length){
                     participantes = participantes + ",";
                }
            }

            //El/los receptor(es) lo(s) sacamos de id(s) pasado(s)
            mu.setTo(participantes);
            h.getListaMensajes().add(mu);
            h.setParticipantes(participantes);

            GestorHilos gh = new GestorHilos(emfBasket,getUsuarioLogado().getId());
            if(gh.Grabar(h, getNumHiloRespuesta())==true){
                getCabecera().setCorrecto(0);
                setError(true);
                log.debug("Error: al escribir el hilo o mensaje");
            }else{
                setError(false);
            }
        }else{
            getCabecera().setCorrecto(0);
            setError(true);
            log.debug("Error: no hay destinatario o mensaje vacio");
        }

        setCabecera(getCabecera());
    }
    */
    

    private void completaDestinatariosConEmisor(){
        boolean sw=false; //no encontrado
        int i=0;
        String user;
        while(i<idsUsuario.length){
            user = idsUsuario[i];
            if(user.compareTo(getUsuarioLogado().getNick())==0){
                sw=true;
            }
            ++i;
        }
        if(sw==false){
            //lo añadimos a la lista de destinatarios
            destinatario += "," + getUsuarioLogado().getNick();
            idsUsuario = destinatario.split(",");
        }
    }
    
    public void archivarConversacionXHR(){
        // borra un mensaje
        log.debug("borrando conversacion: " + archivar);

        cabecera = new InfoCabeceraXHR();
        cabecera.setCorrecto(1);

        if(archivar!=null){
            new GestorHilos(getUsuarioLogado().getId()).archivarHilo(archivar);
        }else{
            cabecera.setCorrecto(0);
        }

        setCabecera(cabecera);
    }

    public void marcarConversacionXHR(){
        // borra un mensaje
        log.debug("Marcando la conversacion: " + getMarcaAnoLeido());

        cabecera = new InfoCabeceraXHR();
        cabecera.setCorrecto(1);

        if(getMarcaAnoLeido()!=null){
            new GestorHilos(getUsuarioLogado().getId()).marcarConversacionXHR(getMarcaAnoLeido(),0);
        }else{
            cabecera.setCorrecto(0);
        }

        setCabecera(cabecera);
    }

    public void cargarConversacionXHR(){
        // carga los mensajes de una conversacion
        log.debug("Cargando conversacion: " + cargarHilo + "idUserLogado: "+getUsuarioLogado().getId());

        if (getUsuarioLogado().getId() > 0) {
            if(cargarHilo!=null){
                GestorHilos gh = new GestorHilos(getUsuarioLogado().getId());
                setDatos(gh.cargarConversacionXHR(cargarHilo));
                if(getDatos()!=null){
                    log.debug("[Cargando conversacion] datos lista" + datos.getListaMensajes().size());

                }
                //actualizamos los mensajes sin leer
                gh = new GestorHilos(getUsuarioLogado().getId());
                setListaHilos(gh.LeerHilos());
                if (getListaHilos()!=null) {
                    int no_leidos=0;
                    for(Hilo h : getListaHilos()){
                        //si un hilo esta sin leer, acumulamos los no leidos
                        if(h.getEstado()==0){
                            ++no_leidos;
                        }
                    }
                    setNumMensajesBandejaEntrada(no_leidos);
                } else {
                    setNumMensajesBandejaEntrada(0);
                }
            }
        }
    }

    public void comprobarNuevosMensajes(){

        int no_leidos=0;
        
        cabecera = new InfoCabeceraXHR();
        cabecera.setCorrecto(1);

        if (getUsuarioLogado().getId() > 0) {
            //comprobamos si el usuario tiene algun mensaje nuevo sin leer
            setListaHilos(new GestorHilos(getUsuarioLogado().getId()).LeerHilos());

            if (getListaHilos()!=null) {

                for(Hilo h : getListaHilos()){
                    //si un hilo esta sin leer, acumulamos los no leidos
                    if(h.getEstado()==0){
                        ++no_leidos;
                    }
                }

            }
            cabecera.setTotal(no_leidos);
        }else{
            cabecera.setCorrecto(0);
        }

        setCabecera(cabecera);
    }

    public void anadirManagerConversacion(){

        log.debug("idDestinatario: " +nicks + "cargarHilo: "+cargarHilo);

        cabecera = new InfoCabeceraXHR();
        cabecera.setCorrecto(1);

        if (getUsuarioLogado().getId() > 0) {
            if (nicks!=null && nicks.length()>0) {

                //intento añadir los managers al hilo
                String nuevosNicks = new GestorHilos(getUsuarioLogado().getId()).anadirManagerConversacionXHR(cargarHilo,nicks);
                
                if(nuevosNicks.compareTo("%error%")!=0){
                    setNicks(nuevosNicks);
                }else{
                    //si no se han podido añadir los managers al hilo
                    cabecera.setCorrecto(0);
                }
            }else{
                cabecera.setCorrecto(0);
            }
        }else{
            cabecera.setCorrecto(0);
        }

        setCabecera(cabecera);

    }

    /* public String abandonarConversacion(){

        String retorno = LOGADO; //se ha escrito bien el mensaje
        MensajeUsuarioV2 mu =null;

        log.debug("[abandonarConversacion] " + cargarHilo);
        
        if (getUsuarioLogado().getId() > 0) {
            if (cargarHilo!=null && cargarHilo.length()>0) {

                Usuario ul = getUsuarioLogado();

                String[] partes = cargarHilo.split("-");
                int id_hilo = Integer.parseInt(partes[0]);

                //creo el mensaje de abandono
                mu = new MensajeUsuarioV2();
                mu.setSender(ul.getId());
                mu.setFrom(ul.getNickMostrar());
                mu.setFromUrl(ul.getNick());
                mu.setAsunto("");
                mu.setTexto("");
                mu.setTipoUsuarioEmisor(MensajeUsuarioV2.TIPO_USUARIO_NORMAL);
                mu.setEstado(2); //abandona la conversacion
                //El/los receptor(es) lo(s) sacamos de id(s) pasado(s)
                mu.setTo("");

                Hilo h = new Hilo();
                h.setCreador(getUsuarioLogado().getId());
                h.setId(id_hilo);
                h.setParticipantes("");
                ArrayList<MensajeUsuarioV2> lista = new ArrayList<MensajeUsuarioV2>();
                lista.add(mu);
                h.setListaMensajes(lista);

                GestorHilos g = new GestorHilos(emfBasket,getUsuarioLogado().getId());

                //si no se graba bien el mensaje o se abandona bien el hilo,error
                if(g.Grabar(h,h.getId())!=true && g.abandonarHilo(h)!=true){
                    retorno = NO_LOGADO;
                    log.debug("Error: al escribir el mensaje/abandonar la conversacion");
                }
            }else{
                retorno = NO_LOGADO;
                log.debug("Error: no hay destinatario");
            }
        }

        return retorno;
    }*/

    public void eliminarMensajes(){

        MensajeUsuarioV2 mu =null;

        log.debug("[eliminarMensajes] IdHilo: " + getIdHilo() + " mensajes: "+  getMensajes());

        if (getUsuarioLogado().getId() > 0) {
            if (getIdHilo()>0 && getMensajes()!=null) {

                Usuario ul = getUsuarioLogado();

                Hilo h = new Hilo();
                h.setCreador(getUsuarioLogado().getId());
                h.setId(getIdHilo());
                h.setParticipantes("");

                //si no se graba bien el mensaje o se abandona bien el hilo,error
                String resultado = new GestorHilos(getUsuarioLogado().getId()).eliminarMensajes(h, mensajes);
            }else{
                log.debug("[eliminarMensajes] Error: parametros incorrectos");
            }
        }

    }

    public String getAsunto() {
        return asunto;
    }

    public void setAsunto(String asunto) {
        this.asunto = asunto;
    }

    public String getDestinatario() {
        return destinatario;
    }

    public void setDestinatario(String idDestinatario) {
        this.destinatario = idDestinatario;
    }

    public boolean isError() {
        return error;
    }

    public void setError(boolean error) {
        this.error = error;
    }

    public String[] getIdsUsuario() {
        return idsUsuario;
    }

    public void setIdsUsuario(String[] idsUsuario) {
        this.idsUsuario = idsUsuario;
    }

    public int getNumHiloRespuesta() {
        return numHiloRespuesta;
    }

    public void setNumHiloRespuesta(int numHiloRespuesta) {
        this.numHiloRespuesta = numHiloRespuesta;
    }

    public InfoCabeceraXHR getCabecera() {
        return cabecera;
    }

    public void setCabecera(InfoCabeceraXHR cabecera) {
        this.cabecera = cabecera;
    }

    public String getArchivar() {
        return archivar;
    }

    public void setArchivar(String archivar) {
        this.archivar = archivar;
    }

    public String getMarcaAnoLeido() {
        return marcaAnoLeido;
    }

    public void setMarcaAnoLeido(String marcaAnoLeido) {
        this.marcaAnoLeido = marcaAnoLeido;
    }

    public String getCargarHilo() {
        return cargarHilo;
    }

    public void setCargarHilo(String cargarHilo) {
        this.cargarHilo = cargarHilo;
    }

    public Hilo getDatos() {
        return datos;
    }

    public void setDatos(Hilo datos) {
        this.datos = datos;
    }

    public List<Hilo> getListaHilos() {
        return listaHilos;
    }

    public void setListaHilos(List<Hilo> listaHilos) {
        this.listaHilos = listaHilos;
    }

    public MensajeUsuarioV2 getRespuesta() {
        return respuesta;
    }

    public void setRespuesta(MensajeUsuarioV2 respuesta) {
        this.respuesta = respuesta;
    }

    public String getNicks() {
        return nicks;
    }

    public void setNicks(String nicks) {
        this.nicks = nicks;
    }

    public int getIdHilo() {
        return idHilo;
    }

    public void setIdHilo(int idHilo) {
        this.idHilo = idHilo;
    }

    public String getMensajes() {
        return mensajes;
    }

    public void setMensajes(String mensajes) {
        this.mensajes = mensajes;
    }

    public String getCuerpo() {
        return cuerpo;
    }

    public void setCuerpo(String mensaje) {
        this.cuerpo = mensaje;
    }

    public int getNumMensajesBandejaEntrada() {
        return numMensajesBandejaEntrada;
    }

    public void setNumMensajesBandejaEntrada(int numMensajesBandejaEntrada) {
        this.numMensajesBandejaEntrada = numMensajesBandejaEntrada;
    }

    public Usuario getUsuarioLogado() {
        return usuarioLogado;
    }

    public void setUsuarioLogado(Usuario usuarioLogado) {
        this.usuarioLogado = usuarioLogado;
    }

    public String escapeHtml(String cadena) {
        /*
         * http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
         * & --> &amp;
         * < --> &lt;
         * > --> &gt;
         * " --> &quot;
         * ' --> &#x27;     &apos; is not recommended
         * / --> &#x2F;     forward slash is included as it helps end an HTML entity
         */

        String retorno = cadena;
        retorno = retorno.replace("&", "&amp;");
        retorno = retorno.replace("<", "&lt;");
        retorno = retorno.replace(">", "&gt;");
        retorno = retorno.replace("\"", "&quot;");
        retorno = retorno.replace("'", "&#x27;");
        retorno = retorno.replace("/", "&#x2F;");

        return retorno;
    }

    public static void main(String[] args) {
        try {
            String mensaje = "123456789-!@#$%^&amp;*()_+|";
            System.out.println(mensaje);

            mensaje = mensaje.replaceAll("%", "<percent>");
            mensaje = URLDecoder.decode(mensaje,"UTF8");
            mensaje = mensaje.replaceAll("<percent>","%");

            System.out.println();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
 
}